#ifndef __CE_SCENE_CLIPPER_H__
#define __CE_SCENE_CLIPPER_H__

#include <export.h>
#include <iobject.h>
#include <math/plane.h>
#include <math/ray.h>
#include <scene/enum.h>
#include <vector>

struct ceVector3f;
class ceBoundingBox;
class ceCamera;
class ceProjector;
class ceSphere;

/**
 * \addtogroup scene
 * @{
 */

/**
 * @brief Interface for performing clipping operations
 */
struct iClipper : public iObject
{
  virtual ~iClipper () { }

  virtual ceClipResult Test(const ceVector3f& v) const = 0;
  virtual ceClipResult Test(const ceVector3f* vs, unsigned count) const = 0;
  virtual ceClipResult Test(const ceBoundingBox& bbox) const = 0;
  virtual ceClipResult Test(const ceSphere& sphere) const = 0;

};

/**
 * \brief Implemenation of the iClipper interface using cePlane objects for clipping
 */
class CE_API cePlaneClipper : public iClipper
{
  CE_OBJECT
private:
  std::vector<cePlane>  _planes;
public:
  cePlaneClipper();

  void AddPlane (const cePlane& plane);

  void Create (const ceCamera& camera, const ceProjector& projector);

  virtual ceClipResult Test(const ceVector3f& v) const;
  virtual ceClipResult Test(const ceVector3f* vs, unsigned count) const;
  virtual ceClipResult Test(const ceBoundingBox& bbox) const;
  virtual ceClipResult Test(const ceSphere& sphere) const;

};

/**
 * \brief Implemenation of the iClipper interface using ceRay objects for clipping
 */
class CE_API ceRayClipper : public iClipper
{
  CE_OBJECT
private:
  std::vector<ceRay>  _rays;

  float               _perPointDistance;
public:
  ceRayClipper();

  void AddRay (const ceRay& ray);

  virtual ceClipResult Test(const ceVector3f& v) const;
  virtual ceClipResult Test(const ceVector3f* vs, unsigned count) const;
  virtual ceClipResult Test(const ceBoundingBox& bbox) const;
  virtual ceClipResult Test(const ceSphere& sphere) const;

};

/** @} */

#endif /* ! __CE_SCENE_CLIPPER_H__ */
